package com.zkingsoft.zkingbase.utils;

import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Images.ImageColumns;
import android.text.TextUtils;
import android.text.format.Formatter;

import com.zkingsoft.zkingbase.base.ZkApplication;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by ytf on 2016/11/10.
 */

public class FileUtils
{

    /**
     * 写文本文件 在Android系统中，文件保存在 /data/data/PACKAGE_NAME/files 目录下
     *
     * @param context
     * @param fileName
     * @param content
     */
    public static void write(Context context, String fileName, String content)
    {
        if (content == null)
            content = "";
        try
        {
            FileOutputStream fos = context.openFileOutput(fileName,
                    Context.MODE_PRIVATE);
            fos.write(content.getBytes());

            fos.close();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 根据文件绝对路径获取文件名
     *
     * @param filePath
     * @return
     */
    public static String getFileName(String filePath)
    {
        if (TextUtils.isEmpty(filePath))
            return "";
        return filePath.substring(filePath.lastIndexOf(File.separator) + 1);
    }

    /**
     * 根据文件的绝对路径获取文件名但不包含扩展名
     *
     * @param filePath
     * @return
     */
    public static String getFileNameNoFormat(String filePath)
    {
        if (TextUtils.isEmpty(filePath))
        {
            return "";
        }
        String fileName = getFileName(filePath);
        return fileName.substring(0, fileName.lastIndexOf("."));
    }

    /**
     * 获取文件后缀名
     *
     * @param fileName
     * @return
     */
    public static String getFileSuffix(String fileName)
    {
        if (TextUtils.isEmpty(fileName))
            return "";

        int point = fileName.lastIndexOf('.');
        return fileName.substring(point + 1);
    }

    /**
     * 获取文件大小
     *
     * @param filePath
     * @return
     */
    public static long getFileSize(String filePath)
    {
        long size = 0;

        File file = new File(filePath);
        if (file != null && file.exists())
        {
            size = file.length();
        }
        return size;
    }

    /**
     * 获取目录文件大小
     *
     * @param dir
     * @return
     */
    public static long getDirSize(File dir)
    {
        if (dir == null)
        {
            return 0;
        }
        if (!dir.isDirectory())
        {
            return 0;
        }
        long dirSize = 0;
        File[] files = dir.listFiles();
        if(files != null && files.length > 0)
        {
            for (File file : files)
            {
                if (file.isFile())
                {
                    dirSize += file.length();
                } else if (file.isDirectory())
                {
                    dirSize += getDirSize(file); // 递归调用继续统计
                }
            }
        }
        return dirSize;
    }

    /***
     * 获得应用的缓存大小
     * @param context
     * @return
     */
    public static String getTotalCacheSize(Context context)
    {
        return Formatter.formatFileSize(context, getDirSize(context.getCacheDir()));
    }

    /***
     * 清楚应用的缓存，并返回清楚后的大小
     * @param context
     * @return
     */
    public static String clearCache(Context context)
    {
        File dir = context.getCacheDir();
        deleteDir(dir);
        return getTotalCacheSize(context);
    }

    /***
     * 删除目录及目录下所有文件
     * @param dir
     * @return
     */
    private static boolean deleteDir(File dir)
    {
        if (dir != null && dir.isDirectory())
        {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++)
            {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success)
                {
                    return false;
                }
            }
        }
        return dir.delete();
    }

    /**
     * 获取目录下文件的个数
     *
     * @param dir
     * @return
     */
    public long getFileList(File dir)
    {
        long count = 0;
        if (dir != null && dir.exists())
        {
            File[] files = dir.listFiles();
            if (files != null && files.length > 0)
            {
                count = files.length;
                for (File file : files)
                {
                    if (file.isDirectory())
                    {
                        count += getFileList(file);// 递归
                        count--;
                    }
                }
            }
        }
        return count;
    }

    public static byte[] streamToBytes(InputStream in) throws IOException
    {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int ch;
        while ((ch = in.read()) != -1)
        {
            out.write(ch);
        }
        byte buffer[] = out.toByteArray();
        out.close();
        return buffer;
    }

    /***
     * 文件转字节数组
     *
     * @param f
     * @return
     */
    private static byte[] fileToByteArray(File f)
    {
        if (f == null || (!f.exists()))
        {
            return null;
        }
        FileInputStream fis = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try
        {
            fis = new FileInputStream(f);
            byte[] buffer = new byte[1024];
            int readCount;
            while ((readCount = fis.read(buffer)) > 0)
            {
                baos.write(buffer, 0, readCount);
            }
            baos.flush();
            return baos.toByteArray();
        } catch (FileNotFoundException e)
        {
            e.printStackTrace();
            return null;
        } catch (IOException e)
        {
            e.printStackTrace();
            return null;
        } finally
        {
            try
            {
                fis.close();
                baos.close();
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    /***
     * 字节数组转文件
     *
     * @param datas
     * @param outFilePath 文件的绝对路径
     * @return
     */
    private static File byteArrayToFile(byte[] datas, String outFilePath)
    {

        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        File f = new File(outFilePath);
        try
        {
            fos = new FileOutputStream(f);
            bos = new BufferedOutputStream(fos);
            bos.write(datas);
            bos.flush();
            return f;
        } catch (FileNotFoundException e)
        {
            e.printStackTrace();
            return null;
        } catch (IOException e)
        {
            e.printStackTrace();
            return null;
        } finally
        {
            try
            {
                if (fos != null)
                {
                    fos.close();
                }
                if (bos != null)
                {
                    bos.close();
                }
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    /**
     * 计算SD卡的剩余空间
     *
     * @return 返回-1，说明没有安装sd卡
     */
    public static long getFreeDiskSpace()
    {
        String status = Environment.getExternalStorageState();
        long freeSpace = 0;
        if (status.equals(Environment.MEDIA_MOUNTED))
        {
            try
            {
                File path = Environment.getExternalStorageDirectory();
                StatFs stat = new StatFs(path.getPath());
                long blockSize = stat.getBlockSize();
                long availableBlocks = stat.getAvailableBlocks();
                freeSpace = availableBlocks * blockSize / 1024;
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        } else
        {
            return -1;
        }
        return (freeSpace);
    }

    /**
     * 创建目录，如果该目录存在则直接返回该路径
     *
     * @param parentPath 父目录，传绝对路径
     * @param directoryName 可以是单个目录， 也可以带子目录 如: /dir 或者 /dir/childDir
     * @return
     */
    public static String mkDir(String parentPath, String directoryName)
    {
        if (!TextUtils.isEmpty(directoryName))
        {
            if (!directoryName.startsWith("/"))
            {
                directoryName = "/" + directoryName;
            }

            File newPath = new File(parentPath, directoryName);
            if (!newPath.exists())
            {
                if (newPath.mkdirs())
                {
                    return newPath.getAbsolutePath();
                }else
                {
                    return null;
                }
            } else
            {
                return newPath.getAbsolutePath();
            }
        }
        return null;
    }


    /**
     * 删除目录(包括：目录里的所有文件)
     *
     * @param fileAbsolutePath
     * @return
     */
    public static boolean deleteDirectory(String fileAbsolutePath)
    {
        boolean status;
        SecurityManager checker = new SecurityManager();
        if (!TextUtils.isEmpty(fileAbsolutePath))
        {
            File newPath = new File(fileAbsolutePath);
            checker.checkDelete(newPath.toString());
            if (newPath.isDirectory())
            {
                String[] listfile = newPath.list();
                try
                {
                    for (int i = 0; i < listfile.length; i++)
                    {
                        File deletedFile = new File(newPath.toString() + "/" + listfile[i].toString());
                        deletedFile.delete();
                    }
                    newPath.delete();
                    status = true;
                } catch (Exception e)
                {
                    e.printStackTrace();
                    status = false;
                }

            } else
                status = false;
        } else
            status = false;
        return status;
    }


    /**
     * 重命名
     *
     * @param oldName
     * @param newName
     * @return
     */
    public static boolean reNamePath(String oldName, String newName)
    {
        File f = new File(oldName);
        return f.renameTo(new File(newName));
    }

    /**
     * 删除文件
     *
     * @param filePath
     */
    public static boolean deleteFileWithPath(String filePath)
    {
        SecurityManager checker = new SecurityManager();
        File f = new File(filePath);
        checker.checkDelete(filePath);
        if (f.isFile())
        {
            f.delete();
            return true;
        }
        return false;
    }

    /**
     * 清空一个文件夹
     *
     * @param filePath
     */
    public static void clearFileWithPath(String filePath)
    {
        List<File> files = FileUtils.listPathFiles(filePath);
        if (files.isEmpty())
        {
            return;
        }
        for (File f : files)
        {
            if (f.isDirectory())
            {
                clearFileWithPath(f.getAbsolutePath());
            } else
            {
                f.delete();
            }
        }
    }

    /**
     * 获取手机外置SD卡的根目录
     *
     * @return
     */
    public static String getExternalSDRoot()
    {

        Map<String, String> evn = System.getenv();

        return evn.get("SECONDARY_STORAGE");
    }

    /**
     * 列出root目录下所有子目录
     *
     * @param root
     * @return 绝对路径
     */
    public static List<String> listPath(String root)
    {
        List<String> allDir = new ArrayList<String>();
        SecurityManager checker = new SecurityManager();
        File path = new File(root);
        checker.checkRead(root);
        // 过滤掉以.开始的文件夹
        if (path.isDirectory())
        {
            for (File f : path.listFiles())
            {
                if (f.isDirectory() && !f.getName().startsWith("."))
                {
                    allDir.add(f.getAbsolutePath());
                }
            }
        }
        return allDir;
    }

    /**
     * 获取一个文件夹下的所有文件
     *
     * @param root
     * @return
     */
    public static List<File> listPathFiles(String root)
    {
        List<File> allDir = new ArrayList<File>();
        SecurityManager checker = new SecurityManager();
        File path = new File(root);
        checker.checkRead(root);
        File[] files = path.listFiles();
        for (File f : files)
        {
            if (f.isFile())
                allDir.add(f);
            else
                listPath(f.getAbsolutePath());
        }
        return allDir;
    }

    /***
     * 在app的主目录下面创建子目录
     * @param newPath
     * @return
     */
    public static String createPathBasedOnApp(String newPath)
    {
        String appPath = getAppPath();
        File f = new File(appPath, newPath);
        if (!f.exists())
        {
            if (f.mkdirs())
            {
                return f.getAbsolutePath();
            } else
            {
                return null;
            }
        } else
        {
            return f.getAbsolutePath();
        }
    }

    /**
     * 截取后缀名
     *
     * @return
     */
    public static String getPathName(String absolutePath)
    {
        int start = absolutePath.lastIndexOf(File.separator) + 1;
        int end = absolutePath.length();
        return absolutePath.substring(start, end);
    }

    /**
     * 获取缓存路径
     *
     * @param context
     * @return
     */
    public static String getCacheDir(Context context, boolean externOrInner)
    {
        String cachePath = null;
        //获取外部缓存目录
        if(externOrInner)
        {
            //准备就绪就返回，否则返回空
            if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
                    || !Environment.isExternalStorageRemovable())
            {
                return context.getExternalCacheDir().getPath();
            }
            return null;
        }else
        {
            //返回内部缓存目录
            return context.getCacheDir().getPath();
        }
    }

    /**
     * 获取应用程序内部缓存文件夹下的指定目录
     *
     * @param context
     * @param dir
     * @return
     */
    public static String getAppCache(Context context, String dir)
    {
        String savePath = context.getCacheDir().getAbsolutePath() + "/" + dir + "/";
        File savedir = new File(savePath);
        if (!savedir.exists())
        {
            savedir.mkdirs();
        }
        return savePath;
    }

    /**
     * 格式化文件长度
     *
     * @param size
     * @return
     */
    public static String formatFileLength(int size)
    {
        long kb = 1024;
        long mb = kb * 1024;
        long gb = mb * 1024;

        if (size >= gb)
        {
            return String.format("%.1f GB", (float) size / gb);
        } else if (size >= mb)
        {
            float f = (float) size / mb;
            return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
        } else if (size >= kb)
        {
            float f = (float) size / kb;
            return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
        } else
            return String.format("%d B", size);
    }

    public static Uri toUri(Context context, Uri fileUri)
    {
        Uri uri = null;
        if (fileUri.getScheme().equals("file"))
        {
            String path = fileUri.getEncodedPath();
            if (path != null)
            {
                path = Uri.decode(path);
                ContentResolver cr = context.getContentResolver();
                StringBuffer buff = new StringBuffer();
                buff.append("(").append(ImageColumns.DATA).append("=")
                        .append("'" + path + "'").append(")");
                Cursor cur = cr.query(Images.Media.EXTERNAL_CONTENT_URI,
                        new String[]{ImageColumns._ID},
                        buff.toString(), null, null);
                int index = 0;
                for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext())
                {
                    index = cur.getColumnIndex(ImageColumns._ID);
                    index = cur.getInt(index);
                }
                if (index == 0)
                {
                } else
                {
                    Uri uri_temp = Uri
                            .parse("content://media/external/images/media/"
                                    + index);
                    if (uri_temp != null)
                    {
                        uri = uri_temp;
                    }
                }
            }
        }
        return uri;
    }

    /**
     * uri转换绝对路径
     *
     * @param context
     * @param uri
     * @return the file path or null
     */
    public static String getRealFilePath(final Context context, final Uri uri)
    {
        if (null == uri)
            return null;
        final String scheme = uri.getScheme();
        String data = null;
        if (scheme == null)
            data = uri.getPath();
        else if (ContentResolver.SCHEME_FILE.equals(scheme))
        {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme))
        {
            Cursor cursor = context.getContentResolver().query(uri,
                    new String[]{ImageColumns.DATA}, null, null, null);
            if (null != cursor)
            {
                if (cursor.moveToFirst())
                {
                    int index = cursor.getColumnIndex(ImageColumns.DATA);
                    if (index > -1)
                    {
                        data = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        return data;
    }


    /**
     * 专为Android4.4设计的从Uri获取文件绝对路径，以前的方法已不好使
     */
    @SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri)
    {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri))
        {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri))
            {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type))
                {
                    return Environment.getExternalStorageDirectory() + "/"
                            + split[1];
                }

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri))
            {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"),
                        Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri))
            {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type))
                {
                    contentUri = Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type))
                {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type))
                {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};

                return getDataColumn(context, contentUri, selection,
                        selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme()))
        {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme()))
        {
            return uri.getPath();
        }

        return null;
    }

    /**
     * contentProvider验证是否是documents目录
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri)
    {
        return "com.android.externalstorage.documents".equals(uri
                .getAuthority());
    }

    /**
     * contentProvider验证是否是downloads目录
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri)
    {
        return "com.android.providers.downloads.documents".equals(uri
                .getAuthority());
    }

    /**
     * contentProvider验证是否是Media目录
     * @param uri
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri)
    {
        return "com.android.providers.media.documents".equals(uri
                .getAuthority());
    }

    /**
     *
     * 通过ContentProvider获得媒体文件路径
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri,
                                       String selection, String[] selectionArgs)
    {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};

        try
        {
            cursor = context.getContentResolver().query(uri, projection,
                    selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst())
            {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally
        {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    public static String getAppPath()
    {
        String appName = ZkApplication.getAppContext().getPackageName();
        appName = appName.substring(appName.lastIndexOf(".") + 1, appName.length());
        return createDirectory(appName);
    }

    /**
     * 创建目录
     *
     * @param directoryName 可以是单个目录， 也可以带子目录 如: /dir 或者 /dir/childDir
     * @return
     */
    public static String createDirectory(String directoryName)
    {
        if (!TextUtils.isEmpty(directoryName))
        {
            if (!directoryName.startsWith("/"))
            {
                directoryName = "/" + directoryName;
            }

            File path = null;
            //初次调用方法时进行判断
            if(((Integer) PreferenceUtils.get("storageState", -1)) == -1)
            {
                //避免找不到文件，在确定外部存储不可用或可用的时候，保存该状态
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
                {
                    path = Environment.getExternalStorageDirectory();
                    //SD可用
                    PreferenceUtils.put("storageState", 1);
                } else
                {
                    path = ZkApplication.getAppContext().getFilesDir();
                    //外部存储不可用，只能使用内部存储
                    PreferenceUtils.put("storageState", 0);
                }
            }else if(((Integer) PreferenceUtils.get("storageState", -1)) == 1)
            {
                //外部存储可用,不可用时抛异常
                if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
                {
                    path = Environment.getExternalStorageDirectory();
                }else
                {
                    throw new RuntimeException("sd卡未准备就绪");
                }
            }else
            {
                //外部存储不可用
                path = ZkApplication.getAppContext().getFilesDir();
            }

            File newPath = new File(path, directoryName);
            if (!newPath.exists())
            {
                if (newPath.mkdirs())
                {
                    return newPath.getAbsolutePath();
                }
            } else
            {
                return newPath.getAbsolutePath();
            }
        }
        return null;
    }

//    public static String createPathBasedOnApp(String newPath)
//    {
//        String appPath = getAppPath();
//        File f = new File(appPath, newPath);
//        if (!f.exists())
//        {
//            if (f.mkdir())
//            {
//                return f.getAbsolutePath();
//            } else
//            {
//                return null;
//            }
//        } else
//        {
//            return f.getAbsolutePath();
//        }
//    }

}
